From 8b7ee4cecb3f0ab4016ad6a259ec0c6818965c66 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 1 Sep 2006 00:42:14 +0100 Subject: [PATCH] [XENBUS] Make frontend drivers shutdown cleanly. This patch makes frontend drivers being shutdown when devices_shutdown() is called and walks down the device tree. Most of it is handled by the xenbus core, which got a new function for the bus->shutdown callback. Signed-off-by: Gerd Hoffmann --- .../drivers/xen/blkfront/blkfront.c | 4 +-- .../drivers/xen/netfront/netfront.c | 7 ++--- .../drivers/xen/xenbus/xenbus_client.c | 7 +++++ .../drivers/xen/xenbus/xenbus_probe.c | 29 +++++++++++++++++-- linux-2.6-xen-sparse/include/xen/xenbus.h | 3 ++ 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index 9f180fd01f..4c44d7608d 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -273,7 +273,7 @@ static void backend_changed(struct xenbus_device *dev, xenbus_dev_fatal(dev, -ENODEV, "bdget failed"); down(&bd->bd_sem); - if (info->users > 0) + if (info->users > 0 && system_state == SYSTEM_RUNNING) xenbus_dev_error(dev, -EBUSY, "Device in use; refusing to close"); else @@ -360,7 +360,7 @@ static void blkfront_closing(struct xenbus_device *dev) xlvbd_del(info); - xenbus_switch_state(dev, XenbusStateClosed); + xenbus_frontend_closed(dev); } diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 136d1ea420..a257cb6064 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -486,7 +486,7 @@ static void backend_changed(struct xenbus_device *dev, struct netfront_info *np = dev->dev.driver_data; struct net_device *netdev = np->netdev; - DPRINTK("\n"); + DPRINTK("%s\n", xenbus_strstate(backend_state)); switch (backend_state) { case XenbusStateInitialising: @@ -1936,11 +1936,10 @@ static void netfront_closing(struct xenbus_device *dev) { struct netfront_info *info = dev->dev.driver_data; - DPRINTK("netfront_closing: %s removed\n", dev->nodename); + DPRINTK("%s\n", dev->nodename); close_netdev(info); - - xenbus_switch_state(dev, XenbusStateClosed); + xenbus_frontend_closed(dev); } diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c index e08e88818e..9b389ec06b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c @@ -138,6 +138,13 @@ int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state) } EXPORT_SYMBOL_GPL(xenbus_switch_state); +int xenbus_frontend_closed(struct xenbus_device *dev) +{ + xenbus_switch_state(dev, XenbusStateClosed); + complete(&dev->down); + return 0; +} +EXPORT_SYMBOL_GPL(xenbus_frontend_closed); /** * Return the path to the error node for the given device, or NULL on failure. diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index 4f5be0fe2e..bcd1f6df06 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -73,6 +73,7 @@ static int xenbus_probe_backend(const char *type, const char *domid); static int xenbus_dev_probe(struct device *_dev); static int xenbus_dev_remove(struct device *_dev); +static void xenbus_dev_shutdown(struct device *_dev); /* If something in array of ids matches this device, return it. */ static const struct xenbus_device_id * @@ -192,6 +193,7 @@ static struct xen_bus_type xenbus_frontend = { .match = xenbus_match, .probe = xenbus_dev_probe, .remove = xenbus_dev_remove, + .shutdown = xenbus_dev_shutdown, }, .dev = { .bus_id = "xen", @@ -246,6 +248,7 @@ static struct xen_bus_type xenbus_backend = { .match = xenbus_match, .probe = xenbus_dev_probe, .remove = xenbus_dev_remove, +// .shutdown = xenbus_dev_shutdown, .uevent = xenbus_uevent_backend, }, .dev = { @@ -349,7 +352,7 @@ static int xenbus_dev_probe(struct device *_dev) const struct xenbus_device_id *id; int err; - DPRINTK(""); + DPRINTK("%s", dev->nodename); if (!drv->probe) { err = -ENODEV; @@ -394,7 +397,7 @@ static int xenbus_dev_remove(struct device *_dev) struct xenbus_device *dev = to_xenbus_device(_dev); struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); - DPRINTK(""); + DPRINTK("%s", dev->nodename); free_otherend_watch(dev); free_otherend_details(dev); @@ -406,6 +409,27 @@ static int xenbus_dev_remove(struct device *_dev) return 0; } +static void xenbus_dev_shutdown(struct device *_dev) +{ + struct xenbus_device *dev = to_xenbus_device(_dev); + unsigned long timeout = 5*HZ; + + DPRINTK("%s", dev->nodename); + + get_device(&dev->dev); + if (dev->state != XenbusStateConnected) { + printk("%s: %s: %s != Connected, skipping\n", __FUNCTION__, + dev->nodename, xenbus_strstate(dev->state)); + goto out; + } + xenbus_switch_state(dev, XenbusStateClosing); + timeout = wait_for_completion_timeout(&dev->down, timeout); + if (!timeout) + printk("%s: %s timeout closing device\n", __FUNCTION__, dev->nodename); + out: + put_device(&dev->dev); +} + static int xenbus_register_driver_common(struct xenbus_driver *drv, struct xen_bus_type *bus) { @@ -588,6 +612,7 @@ static int xenbus_probe_node(struct xen_bus_type *bus, tmpstring += strlen(tmpstring) + 1; strcpy(tmpstring, type); xendev->devicetype = tmpstring; + init_completion(&xendev->down); xendev->dev.parent = &bus->dev; xendev->dev.bus = &bus->bus; diff --git a/linux-2.6-xen-sparse/include/xen/xenbus.h b/linux-2.6-xen-sparse/include/xen/xenbus.h index cd09eb8985..8e259ce777 100644 --- a/linux-2.6-xen-sparse/include/xen/xenbus.h +++ b/linux-2.6-xen-sparse/include/xen/xenbus.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,7 @@ struct xenbus_device { struct xenbus_watch otherend_watch; struct device dev; enum xenbus_state state; + struct completion down; }; static inline struct xenbus_device *to_xenbus_device(struct device *dev) @@ -299,5 +301,6 @@ int __init xenbus_dev_init(void); char *xenbus_strstate(enum xenbus_state state); int xenbus_dev_is_online(struct xenbus_device *dev); +int xenbus_frontend_closed(struct xenbus_device *dev); #endif /* _XEN_XENBUS_H */ -- 2.30.2